<template>
  <div>
    <div class="head-area">
      <el-page-header @back="goBack">
        <template #content>
          <div class="head-content">
            <el-button type="primary" size="small" @click="exportCanvasAsJSON">生成JSON</el-button>
            <el-button type="primary" size="small" @click="exportCanvasAsImage">下载图片</el-button>
          </div>
        </template>
      </el-page-header>
    </div>
  <div class="editor">
    <div class="sidebar left">
      <button @click="addText">添加文本</button>
      <button class="mt16" @click="addImage">添加图片</button>
      <button class="mt16" @click="setBackgroundImage">添加背景图</button>
    </div>
    <canvas id="c" width="600" height="600" class="canvas"></canvas>

    <div class="sidebar right">
      <!-- <div class="sidebar bottom">
        <button @click="zoomIn">放大</button>
        <button @click="zoomOut">缩小</button>
      </div> -->
      <div v-if="!selectedObject">
        <!-- 画布尺寸和背景色编辑选项 -->
        <div class="style-title">画布尺寸:</div>
        <div class="place-line">
          <el-input-number v-model="canvasWidth" size="small" placeholder="宽度" controls-position="right"
            @change="updateCanvasSize" :min="100" :max="1000" :precision="0" />
          <el-input-number v-model="canvasHeight" size="small" placeholder="高度" controls-position="right"
            @change="updateCanvasSize" :min="100" :max="1000" :precision="0" />
        </div>

        <div class="style-title">背景色:</div>
        <el-color-picker style="width: 100%;" v-model="canvasBackgroundColor"
          @change="updateCanvasBackgroundColor"></el-color-picker>
      </div>
      <div v-if="selectedObject">
        <div class="select-head">
          <div class="select-type">{{ selectedObject.type === 'i-text' ? '字体' : '图片' }}</div>
          <a href="JavaScript:;"><i class="el-icon-delete" style="color: red; font-size: 14px;"
              @click="deleteSelectedObjects"> 删除</i></a>
        </div>

        <!-- 字体属性修改 -->
        <div v-if="selectedObject.type === 'i-text'">
          <div class="style-title">颜色:</div>
          <el-color-picker style="width: 100%;" v-model="selectedObject.fill" @change="updateColor"></el-color-picker>

          <div class="style-title">字体大小:</div>
          <el-input-number size="small" v-model="selectedObject.fontSize" controls-position="right"
            @change="canvasRender" :min="1"></el-input-number>
          <div class="style-title">常用属性:</div>
          <div class="font-style">
            <i class="fa fa-bold" @click="updateTextProps('bold')">加粗</i>
            <i class="fa fa-italic" @click="updateTextProps('italic')">斜体</i>
            <i class="fa fa-underline" @click="updateTextProps('underline')">下划线</i>
            <i class="fa fa-strikethrough" @click="updateTextProps('linethrough')">删除线</i>
          </div>
        </div>

        <!-- 图片属性修改 -->
        <div v-if="selectedObject.type === 'image'">
          <div class="style-title">尺寸:</div>
          <div class="place-line">
            <el-input-number v-model="selectedObject.scaleWidth" size="small" placeholder="宽度" controls-position="right"
              @change="updateImgScale" :min="1" :max="1000" :precision="0" />
            <el-input-number v-model="selectedObject.scaleHeight" size="small" placeholder="高度"
              controls-position="right" @change="updateImgScale" :min="1" :max="1000" :precision="0" />
          </div>
        </div>

        <!-- 图片和文字的相同属性 -->
        <div>
          <div class="style-title">位置:</div>
          <div class="place-line">
            <el-input-number v-model="selectedObject.left" size="small" placeholder="X" controls-position="right"
              @change="canvasRender" :precision="0" />
            <el-input-number v-model="selectedObject.top" size="small" placeholder="Y" controls-position="right"
              @change="canvasRender" :precision="0" />
          </div>
          <div class="style-title">不透明度:</div>
          <el-slider v-model="opacityCopy" :min="0" :max="1" :step="0.01" @input="updateOpacity"></el-slider>
        </div>
      </div>
    </div>
  </div>
  </div>
</template>

<script>
import { fabric } from 'fabric';
import jsonData from './initCanvas.json'

export default {
  data() {
    return {
      canvas: null,
      selectedObject: null,
      selectedColor: '#000000',
      jsonData: jsonData,
      canvasWidth: 800, // 初始画布宽度  
      canvasHeight: 600, // 初始画布高度
      canvasBackgroundColor: '#FFF', // 初始画布背景色
      opacityCopy: 1,
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.initCanvas();
      this.loadCanvasFromJson()
    })
  },
  methods: {
    goBack() {
      window.history.go(-1)
    },
    // 修改透明度
    updateOpacity(e) {
      this.selectedObject.opacity = e
      this.canvas.renderAll();
    },
    // 缩放图片
    updateImgScale() {
      const newScaleX = this.selectedObject.scaleWidth / this.selectedObject.width;
      const newScaleY = this.selectedObject.scaleHeight / this.selectedObject.height;
      this.selectedObject.set({
        scaleX: newScaleX,
        scaleY: newScaleY,
      })
      this.canvas.renderAll();
    },
    // 修改文字属性
    updateTextProps(type) {
      if (type == 'bold') {
        this.selectedObject.fontWeight = this.selectedObject.fontWeight == 'normal' ? 'bold' : 'normal'
      }
      if (type == 'italic') {
        this.selectedObject.fontStyle = this.selectedObject.fontStyle == 'normal' ? 'italic' : 'normal'
      }
      if (type == 'linethrough') {
        this.selectedObject.linethrough = !this.selectedObject.linethrough
      }
      if (type == 'underline') {
        this.selectedObject.underline = !this.selectedObject.underline
      }
      this.selectedObject.dirty = true;
      this.canvas.renderAll();
    },
    // 修改属性
    canvasRender(e) {
      this.canvas.renderAll();
    },
    // 更新画布背景色  
    updateCanvasBackgroundColor(color) {
      this.canvas.backgroundColor = color;
      this.canvas.renderAll();
    },
    // 修改画布大小
    updateCanvasSize() {
      this.$nextTick(() => {
        this.canvas.setDimensions({
          width: this.canvasWidth,
          height: this.canvasHeight
        })
      })

      // 获取当前背景图  
      const backgroundImage = this.canvas.getObjects().find(obj => obj.is_background);
      if (backgroundImage) {
        // 计算新的缩放比例以填满画布  
        const newScaleX = this.canvasWidth / backgroundImage.width;
        const newScaleY = this.canvasHeight / backgroundImage.height;
        backgroundImage.set({
          scaleX: newScaleX,
          scaleY: newScaleY,
        });
      }
      this.canvas.renderAll(); // 重新渲染画布
    },
    // 放大画布
    zoomIn() {
      const currentZoom = this.canvas.getZoom();
      this.canvas.setZoom(currentZoom * 1.1);
      this.canvas.renderAll();
    },
    // 缩小画布
    zoomOut() {
      const currentZoom = this.canvas.getZoom();
      this.canvas.setZoom(currentZoom * 0.9);
      this.canvas.renderAll();
    },
    // 新增方法：从JSON加载画布  
    loadCanvasFromJson() {
      this.canvas.clear(); // 清空当前画布  
      this.canvas.loadFromJSON(this.jsonData, this.canvas.renderAll.bind(this.canvas));
    },
    // 删除元素
    deleteSelectedObjects() {
      const selectedObjects = this.canvas.getActiveObjects();
      if (selectedObjects.length > 0) {
        selectedObjects.forEach(obj => {
          this.canvas.remove(obj);
        });
        this.canvas.renderAll();
        // 清除 selectedObject 引用，如果你需要在其他地方使用它  
        this.selectedObject = null;
      }
    },
    initCanvas() {
      this.canvas = new fabric.Canvas('c', {
        backgroundColor: this.canvasBackgroundColor,
        width: 800,
        height: 576,
      });
      this.canvas.on('mouse:up', (e) => {
        if (e.target) {
          this.selectedObject = e.target;
          this.opacityCopy = this.selectedObject.opacity
        } else {
          this.selectedObject = null
        }
      });
      this.canvas.on('object:scaling', (e) => {
        if (e.target && e.target.type === 'image') {
          console.log('scaling', e);
          // 更新输入框中的宽度和高度值
          this.selectedObject.scaleWidth = e.target.width * e.target.scaleX;
          this.selectedObject.scaleHeight = e.target.height * e.target.scaleY;
        }
      });
    },
    setBackgroundImage(imageUrl) {
      fabric.Image.fromURL(imageUrl, (img) => {
        console.log('img', img);
        // 获取画布的宽度和高度  
        const canvasWidth = this.canvas.getWidth();
        const canvasHeight = this.canvas.getHeight();
        // 直接设置图像的宽度和高度为画布的宽度和高度  
        img.set({
          left: 0,
          top: 0,
          scaleX: canvasWidth / img.width,
          scaleY: canvasHeight / img.height,
          selectable: false, // 让背景图不可选  
          evented: false,     // 让背景图不触发事件  
          is_background: true // 背景图标识  
        });

        // 遍历画布上的所有对象，查找并删除已存在的背景图  
        this.canvas.getObjects().forEach((obj) => {
          if (obj.is_background) {
            this.canvas.remove(obj);
          }
        });
        // 将背景图添加到画布上  
        this.canvas.add(img);
        // 如果有必要，可以将背景图放在所有其他对象的底层  
        this.canvas.sendToBack(img);
        // 重新渲染画布  
        this.canvas.renderAll();
      }, { crossOrigin: 'anonymous' });
    },

    addText() {
      const text = new fabric.IText('点击编辑', {
        left: 100,
        top: 100,
        fontSize: 30,
        fontFamily: 'arial',
        fill: '#333',
        originX: 'left',
        originY: 'top'
      });
      this.canvas.add(text);
    },
    addImage() {
      fabric.Image.fromURL('https://img1.baidu.com/it/u=3646728960,3598744100&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1729616400&t=a7ffaf977f0cb15a6f9a86b573e84117', (img) => {
        // 假设 this.canvas 是已经初始化并设置好大小的 Fabric.js 画布  
        const canvasWidth = this.canvas.getWidth();
        const canvasHeight = this.canvas.getHeight();
        const maxWidth = canvasWidth * 0.6; // 计算图片允许的最大宽度  
        const maxHeight = canvasHeight * 0.3;

        // 计算缩放比例   
        let scale = Math.min(maxWidth / img.width, maxHeight / img.height);

        // 如果图片的原始高度缩放后仍然适合画布（这里假设高度不是关键限制），则直接使用上述比例  
        // 否则，你可能需要根据实际情况调整高度或保持宽高比（这里只处理宽度限制）  

        // 应用缩放比例  
        img.scale(scale).set({
          left: (canvasWidth - img.width * scale) / 2, // 可选：居中图片  
          top: (canvasHeight - img.height * scale) / 2,
          angle: 0,  // 你可以根据需要调整图片的旋转角度  
          sys_filed: 'demo',
          scaleWidth: img.width * scale,
          scaleHeight: img.height * scale
        });

        // 将图片添加到画布  
        this.canvas.add(img);

        // 重新渲染画布以显示新添加的图片  
        this.canvas.renderAll();
      }, { crossOrigin: 'anonymous' });
    },
    updateColor(newColor) {
      this.selectedObject.fill = newColor
      this.selectedObject.dirty = true;
      this.canvas.renderAll();
    },
    updateScale(e) {
      if (this.selectedObject) {
        this.selectedObject.scaleX = this.selectedObject.scaleY = parseFloat(e.target.value);
        this.canvas.renderAll();
      }
    },

    exportCanvasAsJSON() {

      // 遍历每个对象，确保 scaleX 和 scaleY 保留更高的精度
      this.canvas.forEachObject((obj) => {
        obj.scaleX = parseFloat(obj.scaleX.toFixed(16));
        obj.scaleY = parseFloat(obj.scaleY.toFixed(16));
      });
      console.log('this.canvas', this.canvas);
      // 获取画布上所有对象的JSON表示  
      const jsonData = this.canvas.toJSON(['selectable', 'evented', 'is_background', 'sys_filed', 'scaleX', 'scaleY', 'scaleWidth', 'scaleHeight']); // 你可以根据需要包含或排除属性  
      console.log('jsonData', jsonData);

      // 将JSON对象转换为字符串  
      const jsonString = JSON.stringify(jsonData, null, 2);

      // 创建一个Blob对象  
      const blob = new Blob([jsonString], { type: 'text/json' });

      // 创建一个指向blob的URL  
      const url = window.URL.createObjectURL(blob);

      // 创建一个临时的a标签用于下载  
      const a = document.createElement('a');
      a.href = url;
      a.download = 'canvas_data.json'; // 指定下载的文件名  
      document.body.appendChild(a);
      a.click(); // 模拟点击以触发下载  

      // 清理  
      document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    },

    exportCanvasAsImage() {
      // 设置图片的质量和格式，这里以PNG格式为例，质量为0.8  
      const imageUrl = this.canvas.toDataURL({  
          format: 'png',  
          quality: 0.8  
      });

      // 创建一个指向该DataURL的a标签用于下载
      const a = document.createElement('a');
      a.href = imageUrl;
      a.download = 'canvas_image.png'; // 指定下载的文件名
      document.body.appendChild(a);
      a.click(); // 模拟点击以触发下载
      document.body.removeChild(a);
      window.URL.revokeObjectURL(imageUrl);
    }
  }
};
</script>

<style>
.head-area {
  padding: 20px 24px;
  border-bottom: 1px solid #eee;
}
.head-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 500;
}
.mt16 {
  margin-top: 16px;
}

.editor {
  display: flex;
  height: 100vh;
}

.sidebar {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* justify-content: space-around; */
  align-items: center;
  padding: 20px;
  background-color: #f0f0f0;
}

.select-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.select-type {
  font-size: 18px;
  font-weight: 500;
}

.style-title {
  color: #7f8792;
  margin: 32px 0 16px;
  font-size: 16px;
}

.font-style {
  background-color: #F5F7FA;
  padding: 8px 0;
  border-radius: 3px;
  font-size: 16px;
  display: flex;
  justify-content: space-around;

  i {
    cursor: pointer
  }
}

.place-line {
  display: flex;
  gap: 16px;
}

::v-deep .el-input-group__append,
.el-input-group__prepend {
  padding: 0 10px;
}

::v-deep .el-color-picker__trigger {
  width: 100%;
}

.canvas {
  flex: 2;
  border: 1px solid #ccc;
}
</style>